{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_selection:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Selection\n",
    "\n",
    "This module defines the mating selection during the execution of a genetic algorithm. At the beginning of the mating, process parents need to be selected to be mated using the crossover operation.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Either a selection objective is created directly or the convenience function [get_selection](/api/factory.html#pymoo.factory.get_selection) is used."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " \n",
    " \n",
    " \n",
    " "
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_selection_random:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Random Selection ('random')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, we randomly pick solutions from the current population to be used for recombination. The implementation uses a permutation to avoid repetitive individuals. For instance, let us consider the case where only two parents are desired to be selected: The permutation (5,2,3,4,1,0), will lead to the parent selection of (5,2), (3,4), (1,0), where no parent can participate twice for mating."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymoo.factory import get_selection\n",
    "selection = get_selection('random')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " "
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. _nb_selection_tournament:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tournament Selection ('tournament')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It has been shown that tournament pressure is helpful for faster convergence. This implementation provides the functionality to define a tournament selection very generic. \n",
    "Below we show a binary tournament selection (two individuals are participating in each competition).\n",
    "\n",
    "Having defined the number of participants, the winner needs to be written to an output array. Here, we use the fitness values (if constraints should be considered, CV should be added as well) to achieve that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.00081646  0.00056511]\n"
     ]
    }
   ],
   "source": [
    "from pymoo.factory import get_selection\n",
    "\n",
    "# simple binary tournament for a single-objective algorithm\n",
    "def binary_tournament(pop, P, algorithm, **kwargs):\n",
    "    \n",
    "    # The P input defines the tournaments and competitors\n",
    "    n_tournaments, n_competitors = P.shape\n",
    "    \n",
    "    if n_competitors != 2:\n",
    "        raise Exception(\"Only pressure=2 allowed for binary tournament!\")\n",
    "    \n",
    "    # the result this function returns\n",
    "    import numpy as np\n",
    "    S = np.full(n_tournaments, -1, dtype=np.int)\n",
    "\n",
    "    # now do all the tournaments\n",
    "    for i in range(n_tournaments):\n",
    "        a, b = P[i]\n",
    "        \n",
    "        # if the first individiual is better, choose it\n",
    "        if pop[a].F < pop[a].F:\n",
    "            S[i] = a\n",
    "            \n",
    "        # otherwise take the other individual\n",
    "        else:\n",
    "            S[i] = b\n",
    "            \n",
    "    return S\n",
    "    \n",
    "\n",
    "selection = get_selection('tournament', {'pressure' : 2, 'func_comp' : binary_tournament})\n",
    "\n",
    "\n",
    "\n",
    "# Now for test purposes let us use the selection inplace\n",
    "from pymoo.optimize import minimize\n",
    "from pymoo.factory import get_algorithm\n",
    "from pymoo.factory import get_problem\n",
    "\n",
    "res = minimize(\n",
    "    get_problem(\"rastrigin\"), \n",
    "    get_algorithm(\"ga\", \n",
    "                           pop_size=100, \n",
    "                           eliminate_duplicates=True),\n",
    "    termination=('n_gen', 50), \n",
    "    verbose=False)\n",
    "\n",
    "print(res.X)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### API"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ".. autofunction:: pymoo.factory.get_selection\n",
    "    :noindex:\n",
    "    \n",
    ".. autofunction:: pymoo.model.selection.Selection\n",
    "    :noindex:"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Raw Cell Format",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
